<?php
// +----------------------------------------------------------------------
// | 关闭订单接口
// +----------------------------------------------------------------------
// | Author: @蓝优 荣誉出品
// +----------------------------------------------------------------------
class WxPayCloseOrder
{
    private $appid;
    private $mch_id;
    private $key;
    private $out_trade_no;

    public function __construct($appid, $mch_id, $key, $out_trade_no)
    {
        $this->appid = $appid;
        $this->mch_id = $mch_id;
        $this->key = $key;
        $this->out_trade_no = $out_trade_no;
    }

    public function closeOrder()
    {
        $url = "https://api.mch.weixin.qq.com/pay/closeorder";
        
        $nonce_str = md5(time());
        $data = [
            'appid' => $this->appid,
            'mch_id' => $this->mch_id,
            'out_trade_no' => $this->out_trade_no,
            'nonce_str' => $nonce_str,
        ];

        // 按照字段名排序
        ksort($data);

        // 生成签名
        $sign_str = urldecode(http_build_query($data)) . '&key=' . $this->key;
        $sign = md5($sign_str);

        // 添加签名到参数中
        $data['sign'] = $sign;

        // 发送XML请求
        $xml = $this->arrayToXml($data);
        $response = $this->postXmlCurl($xml, $url);

        // 处理返回结果
        $result = $this->xmlToArray($response);
        return $result;
    }

    // 数组转XML
    private function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    // XML转数组
    private function xmlToArray($xml)
    {
        $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $values;
    }

    // POST XML CURL
    private function postXmlCurl($xml, $url, $second = 30)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
}

// 使用示例
$appid = '你的appid';
$mch_id = '你的商户号';
$key = '你的密钥';
$out_trade_no = $_GET['out_trade_no'];

$closeOrder = new WxPayCloseOrder($appid, $mch_id, $key, $out_trade_no);
$response = $closeOrder->closeOrder();

echo json_encode($response);
?>